﻿/****************************************************************************************************************
*                                                                                                               *
* Copyright (C) 2011 5173.com                                                                                   *
* This project may be copied only under the terms of the Apache License 2.0.                                    *
* Please visit the project Home Page http://bqqapicsharp.codeplex.com/ for more detail.                         *
*                                                                                                               *
****************************************************************************************************************/

namespace BQQAPIClient.Core.Protocol
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using BQQAPIClient.Core.Utility;

    internal abstract class AbstractOperationPackage
    {
        private static readonly ushort CLTVER = 1;
        private static readonly ushort SRVVER = 1;

        private Header header;
        private ExtraHeader extraHeader;

        protected abstract ushort Cmd { get; }
        protected abstract ushort SubCmd { get; }
        protected virtual TLVList OtherData 
        {
            get
            {
                return new TLVList();
            }
        }

        internal AbstractOperationPackage()
        {
            header = new Header
            {
                usCmd = Cmd,
            };
            extraHeader = new ExtraHeader
            {
                usSubCmd = SubCmd,
                usCltVer = CLTVER,
                usSrvVer = SRVVER,
                uiSeqNum = BQQAPI.GetSeqNum(),
            };
        }

        internal byte[] GetBytes()
        {
            var otherDataBytes = new List<byte>();
            OtherData.ForEach(item => otherDataBytes.AddRange(item.GetBytes()));
            extraHeader.usOtherLen = (ushort)otherDataBytes.Count;
            header.usExtraLen = (ushort)(extraHeader.usOtherLen + Marshal.SizeOf(extraHeader));

            List<byte> allBytes = new List<byte>();
            if (SubCmd != 0)
            {
                allBytes.AddRange(header.StructToBytes());
                allBytes.AddRange(extraHeader.StructToBytes());
            }
            else
            {
                header.usExtraLen = Convert.ToUInt16(otherDataBytes.Count);
                allBytes.AddRange(header.StructToBytes());
            }
            allBytes.AddRange(otherDataBytes);
            return allBytes.ToArray();
        }
    }
}
